并发基础1(线程进程、Voliate、synchronize锁实现) | 您所在的位置:网站首页 › voliate 可见性 › 并发基础1(线程进程、Voliate、synchronize锁实现) |
目录 1:java内存模型 1.1:计算机的内存模型 2:Voliate关键字 2.1:voliate不能保证线程安全(可见性分析) 2.2:voliate禁止指令重排 3:java的线程 3.1:线程和进程 3.2:线程的状态 4:线程安全 4.1:synchronize关键字(悲观锁,阻塞同步) 4.2:Cpmpare And Swip(乐观锁,非阻塞同步CAS) 4.3:CAS怎么使用(显式调用和隐式调用) 5:锁优化(synchronize优化) 5.1:自旋和自适应自旋 5.2:锁消除 5.3:锁粗化 5.4:轻量级锁(绝大部分锁在整个周期都不存竞争) 5.5:偏向锁(无竞争的单线程执行,有竞争的时候才会释放锁) 5.6:偏向锁、轻量级锁、重量级锁对比 6: 什么是死锁?如何避免死锁? 6.1:什么是死锁 6.2:如何避免死锁? 1:java内存模型 1.1:计算机的内存模型在计算机的内存模型中cpu和内存之间的速度存在数量级所以引入了高速缓存,高速缓存会导致到底以哪个处理器的缓存为主,同步到主内存,这个时候有有了缓存一致性协议,来保证缓存一致性。 指令重排:例如一下五行代码,前四行的在计算机cpu的执行顺序不一定是12345,也可以是13245或者34125,但是第五步的顺序不会变,这种指令重排不会影响最后的计算结果。 int a=1; a++; int b=5; b++; int c=a+b; 1.2:java内存模型 java的内存模型屏蔽掉了计算机硬件和操作系统的差异,但是没有限制处理器使用缓存和主内存进行交互,也没有限制编译器在执行过程中的指令重排这类优化措施。 voliate关键字有两个作用(可见性和禁止指令重排) 1:可见性:保证在多个线程的情况下,线程一把int a的值修改为5的时候,其他线程也能立即知道int a=5,实现的方法是线程1把int a=5,会把a=5的是立马通过缓存同步到主内存,然后其他线程使用a之前会从主内存刷新一次,得到被线程1修改的值为5. 2:有序性:有序性的意思的在本线程内观察,所有操作都是有序的(线程内是串行的),但是在另一个线程观察本线程,所有操作都是无序的(主要是指指令重排现象和工作内存与主内存同步)。voliate和synchronize两个关键字来保证线程操作之间的有序性。 2.1:voliate不能保证线程安全(可见性分析)预期结果:10个线程同时执行,每一个此线程都把i累加到1000.最后的结果应该是10000. 实际结果:多次运行,大部分结果都不足10000 结论分析:i++,不是原子性操作,线程1把i的值赋值的10,这个时候后线程2根据可见性也得到了10,但是线程1接着执行累加把i的值赋值到250,这个时候线程2依然拿到的值是10是过期数据,入栈++后的值为11,把11同步到了主内存,触发了线程1从主内存同步的得到值为11,这个时候会导致线程一的结果错误。 public class VoliteTest { //voliate关键字保证了此变量在各个线程中是一致的 public static volatile int id=1; public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub Thread[] ths=new Thread[10]; for(int i=0;i1) { Thread.yield(); } System.out.println("========================"); System.out.println("ID的值是:"+id); } //该方法可以通过加锁实现线程安全 public static void add() { for(int i = 0;i |
CopyRight 2018-2019 实验室设备网 版权所有 |